package cn.lkk.samples.lang.reflection;

import cn.lkk.samples.lang.inheritance.objectClass.Employee;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 通过反射，实现了一个通用的 toString 方法，打印对象中的所有方法。
 */
 public class ObjectAnalyzer {

    /**
     * 用于记录访问过的对象
     */
    private List<Object> visited = new ArrayList<>();

    /**
     * 获得一个对象的打印字符串
     *
     * @param obj 要打印的对象
     * @return 参数的字符串表示
     */
    public String toString(Object obj) throws IllegalAccessException {
        //如果对象为空
        if (obj == null)
            return "null";

        //如果对象访问过了
        if (visited.contains(obj))
            return "...";

        Class clazz = obj.getClass();
        String r = "";

        //如果是字符串
        if (clazz == String.class)
            return (String) obj;

        visited.add(obj);

        //如果对象是数组
        if (clazz.isArray()) {
            r = r + clazz + "[]{";
            for (int i = 0; i < Array.getLength(obj); ++i) {
                Object value = Array.get(obj, i);
                if (i > 0)
                    r += ", ";
                if (clazz.getComponentType().isPrimitive())
                    r += value;
                else
                    r += toString(value);
            }
            r += "}";
            return r;
        }

        //如果不是数组，那么继续
        r += clazz.getName();
        do {
            r += "[";
            Field[] fields = clazz.getDeclaredFields();
            AccessibleObject.setAccessible(fields, true);
            for (int i = 0; i < fields.length; ++i) {
                Field field = fields[i];
                //打印所有的非静态字段
                if (!Modifier.isStatic(field.getModifiers())) {
                    //打印逗号
                    if (i > 0)
                        r += ", ";
                    //打印字段名
                    String filedName = field.getName();
                    r += filedName + "=";
                    //打印字段值
                    Object value = field.get(obj);
                    if (field.getType().isPrimitive())
                        r += value;
                    else
                        r += toString(value);
                }
            }
            r += "]";
            clazz = clazz.getSuperclass();
        } while (clazz != null);
        return r;
    }

    public static void main(String[] args) throws IllegalAccessException {
        Integer[] ints = {1, 2, 3, 4, 5};
        Employee employee = new Employee("Bob", 500, 2015, 12, 1);
        String str = "hello";
        System.out.println(new ObjectAnalyzer().toString(employee));
    }
}